package wkt.exam;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Maps;
import net.xnzn.framework.id.Id;
import net.xnzn.framework.secure.filter.annotation.RequiresAuthentication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import wkt.RequireStudentLogin;
import wkt.WebUtils;
import wkt.question.ExamTipsConfirm;
import wkt.question.ExamTipsConfirmMapper;
import wkt.question.Question;
import wkt.question.QuestionMapper;
import wkt.student.Student;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/exam")
@Validated

public class ExamController {
    @Autowired
    private ExamTipsConfirmMapper examTipsConfirmMapper;
    @Autowired
    private QuestionMapper questionMapper;
    @Autowired
    private ExamRecordMapper examRecordMapper;
    @Autowired
    private ExamRecordAnswerMapper examRecordAnswerMapper;
    @Autowired
    private ExamWrongQuestionMapper examWrongQuestionMapper;

    @PostMapping("/home/status")
    @RequireStudentLogin
    public ExamHomeStatus status(@RequestBody ExamHomeStatus examHomeStatus) {
        final Long studentId = WebUtils.studentId();
        ExamHomeStatus status = new ExamHomeStatus();

        final Long confirmedTipsCount = examTipsConfirmMapper.selectCount(Wrappers.lambdaQuery(ExamTipsConfirm.class)
                .eq(ExamTipsConfirm::getBasicCode, examHomeStatus.getBasicCode())
                .eq(ExamTipsConfirm::getStudentId, studentId));
        status.setAttentionRead(confirmedTipsCount > 0);

        //每种题型题目数量
        final QueryWrapper<Question> questionQueryWrapper = new QueryWrapper<>();
        final List<Map<String, Object>> counts = questionMapper.selectMaps(questionQueryWrapper.select("type,count(1) as count").eq("basic_code", examHomeStatus.getBasicCode()).eq("state", "NORMAL").groupBy("type"));
        if (CollUtil.isNotEmpty(counts)) {
            for (Map<String, Object> map : counts) {
                if ("DANXUAN".equals(map.get("type"))) {
                    status.setDanXuanQuestionCount((Long) map.get("count"));
                    continue;
                }
                if ("DUOXUAN".equals(map.get("type"))) {
                    status.setDuoXuanQuestionCount((Long) map.get("count"));
                    continue;
                }
                if ("TIANKONG".equals(map.get("type"))) {
                    status.setTianKongQuestionCount((Long) map.get("count"));
                    continue;
                }
                if ("MINGCIJIESHI".equals(map.get("type"))) {
                    status.setMingCiJieShiQuestionCount((Long) map.get("count"));
                    continue;
                }
                if ("LUNSHU".equals(map.get("type"))) {
                    status.setLunShuQuestionCount((Long) map.get("count"));
                }
            }
        }

        //每种题型当前已答题目数量
        final QueryWrapper<ExamRecord> examRecordQueryWrapper = new QueryWrapper<>();
        final List<Map<String, Object>> examRecordCounts = examRecordMapper.selectMaps(examRecordQueryWrapper.select("type,count(distinct question_id) as count").eq("student_id", studentId).eq("basic_code", examHomeStatus.getBasicCode()).eq("state", "NORMAL").groupBy("type"));
        if (CollUtil.isNotEmpty(examRecordCounts)) {
            for (Map<String, Object> map : examRecordCounts) {
                if ("DANXUAN".equals(map.get("type"))) {
                    status.setDanXuanAnsweredQuestionCount((Long) map.get("count"));
                    continue;
                }
                if ("DUOXUAN".equals(map.get("type"))) {
                    status.setDuoXuanAnsweredQuestionCount((Long) map.get("count"));
                    continue;
                }
                if ("TIANKONG".equals(map.get("type"))) {
                    status.setTianKongAnsweredQuestionCount((Long) map.get("count"));
                    continue;
                }
                if ("MINGCIJIESHI".equals(map.get("type"))) {
                    status.setMingCiJieShiAnsweredQuestionCount((Long) map.get("count"));
                    continue;
                }
                if ("LUNSHU".equals(map.get("type"))) {
                    status.setLunShuAnsweredQuestionCount((Long) map.get("count"));
                }
            }
        }

        //每种题型错题本内题目数量
        final QueryWrapper<ExamWrongQuestion> examWrongQuestionQueryWrapper = new QueryWrapper<>();
        final List<Map<String, Object>> examWrongQuestionCounts = examWrongQuestionMapper.selectMaps(examWrongQuestionQueryWrapper.select("type,count(distinct question_id) as count").eq("student_id", studentId).eq("basic_code", examHomeStatus.getBasicCode()).groupBy("type"));
        if (CollUtil.isNotEmpty(examWrongQuestionCounts)) {
            for (Map<String, Object> map : examWrongQuestionCounts) {
                if ("DANXUAN".equals(map.get("type"))) {
                    status.setDanXuanAnsweredWrongQuestionCount((Long) map.get("count"));
                    continue;
                }
                if ("DUOXUAN".equals(map.get("type"))) {
                    status.setDuoXuanAnsweredWrongQuestionCount((Long) map.get("count"));
                    continue;
                }
                if ("TIANKONG".equals(map.get("type"))) {
                    status.setTianKongAnsweredWrongQuestionCount((Long) map.get("count"));
                    continue;
                }
                if ("MINGCIJIESHI".equals(map.get("type"))) {
                    status.setMingCiJieShiAnsweredWrongQuestionCount((Long) map.get("count"));
                    continue;
                }
                if ("LUNSHU".equals(map.get("type"))) {
                    status.setLunShuAnsweredWrongQuestionCount((Long) map.get("count"));
                }
            }
        }
        return status;
    }

    @PostMapping("/answer")
    @Transactional(rollbackFor = Exception.class)
    @RequireStudentLogin
    public Long answer(@RequestBody ExamRecord examRecord) {
        if (examRecord.getSeqId() == null) examRecord.setSeqId(Id.next());
        examRecord.setId(Id.next());
        examRecord.setStudentId(WebUtils.studentId());
        examRecordMapper.insert(examRecord);

        if (ArrayUtil.isNotEmpty(examRecord.getAnswerId())) {
            for (Long answerId : examRecord.getAnswerId()) {
                examRecordAnswerMapper.insert(new ExamRecordAnswer(examRecord.getId(), answerId));
            }
        }

        if (examRecord.isFromWrongBook()) {
            if (examRecord.isRights() && examRecord.isRemoveOnAnswerRight()) {
                examWrongQuestionMapper.delete(Wrappers.lambdaUpdate(ExamWrongQuestion.class)
                        .eq(ExamWrongQuestion::getQuestionId, examRecord.getQuestionId())
                        .eq(ExamWrongQuestion::getStudentId, examRecord.getStudentId())
                        .eq(ExamWrongQuestion::getSource, "EXAM"));
            }
        } else {
            if (!examRecord.isRights()) {
                Long aa = examWrongQuestionMapper.selectCount(Wrappers.lambdaQuery(ExamWrongQuestion.class)
                        .eq(ExamWrongQuestion::getQuestionId, examRecord.getQuestionId())
                        .eq(ExamWrongQuestion::getStudentId, examRecord.getStudentId()));
                if (aa < 1) {
                    examWrongQuestionMapper.insert(new ExamWrongQuestion().setQuestionId(examRecord.getQuestionId()).setStudentId(examRecord.getStudentId()).setType(examRecord.getType()).setSource("EXAM").setBasicCode(examRecord.getBasicCode()));
                }
            }
        }

        return examRecord.getSeqId();
    }

    @PostMapping("/star-question")
    @Transactional(rollbackFor = Exception.class)
    @RequireStudentLogin
    public void starQuestion(@RequestBody ExamWrongQuestion examWrongQuestion) {
        examWrongQuestion.setStudentId(WebUtils.studentId());
        if (examWrongQuestion.isStar()) {
            Long aa = examWrongQuestionMapper.selectCount(Wrappers.lambdaQuery(ExamWrongQuestion.class)
                    .eq(ExamWrongQuestion::getQuestionId, examWrongQuestion.getQuestionId())
                    .eq(ExamWrongQuestion::getStudentId, examWrongQuestion.getStudentId()));
            if (aa < 1) {
                examWrongQuestionMapper.insert(new ExamWrongQuestion().setQuestionId(examWrongQuestion.getQuestionId()).setStudentId(examWrongQuestion.getStudentId()).setType(examWrongQuestion.getType()).setSource("STAR").setBasicCode(examWrongQuestion.getBasicCode()));
            }
            return;
        }
        examWrongQuestionMapper.delete(Wrappers.lambdaUpdate(ExamWrongQuestion.class)
                .eq(ExamWrongQuestion::getQuestionId, examWrongQuestion.getQuestionId())
                .eq(ExamWrongQuestion::getStudentId, examWrongQuestion.getStudentId()));
    }

    @PostMapping("/wrong/statistics")
    @RequireStudentLogin
    public WrongStatistics wrongStatistics(Long studentId) {
        if (studentId == null) studentId = WebUtils.studentId();
        Map<String, WrongBookQuestionCount> basicCode_wrongStatistics = Maps.newHashMap();

        //每种题型错题本内题目数量
        final QueryWrapper<ExamWrongQuestion> examWrongQuestionQueryWrapper = new QueryWrapper<>();
        final List<Map<String, Object>> examWrongQuestionCounts = examWrongQuestionMapper.selectMaps(examWrongQuestionQueryWrapper.select("basic_code,type,count(distinct question_id) as count").eq("student_id", studentId).groupBy("basic_code", "type"));
        if (CollUtil.isNotEmpty(examWrongQuestionCounts)) {
            for (Map<String, Object> map : examWrongQuestionCounts) {
                final WrongBookQuestionCount basicCode = basicCode_wrongStatistics.getOrDefault((String) map.get("basic_code"), new WrongBookQuestionCount());
                if ("DANXUAN".equals(map.get("type"))) {
                    basicCode.setDanXuanAnsweredWrongQuestionCount((Long) map.get("count"));
                } else if ("DUOXUAN".equals(map.get("type"))) {
                    basicCode.setDuoXuanAnsweredWrongQuestionCount((Long) map.get("count"));
                } else if ("TIANKONG".equals(map.get("type"))) {
                    basicCode.setTianKongAnsweredWrongQuestionCount((Long) map.get("count"));
                } else if ("MINGCIJIESHI".equals(map.get("type"))) {
                    basicCode.setMingCiJieShiAnsweredWrongQuestionCount((Long) map.get("count"));
                } else if ("LUNSHU".equals(map.get("type"))) {
                    basicCode.setLunShuAnsweredWrongQuestionCount((Long) map.get("count"));
                }
                basicCode_wrongStatistics.put((String) map.get("basic_code"), basicCode);
            }
        }


        return new WrongStatistics(
//                examRecordMapper.totalCount(WebUtils.studentId(), null,null),
//                examRecordMapper.totalCount(WebUtils.studentId(), false,null),
//                examRecordMapper.totalCount(WebUtils.studentId(), false,LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))),
                basicCode_wrongStatistics,
                examRecordMapper.selectCount(Wrappers.lambdaQuery(ExamRecord.class).eq(ExamRecord::getStudentId, studentId)),
                examRecordMapper.selectCount(Wrappers.lambdaQuery(ExamRecord.class).eq(ExamRecord::getStudentId, studentId).eq(ExamRecord::isRights, "0")),
                examRecordMapper.selectCount(Wrappers.lambdaQuery(ExamRecord.class).eq(ExamRecord::getStudentId, studentId).eq(ExamRecord::isRights, "0").ge(ExamRecord::getCreateTime, LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))))
        );
    }

    @PostMapping("/wrong/statistics-for-pc")
    @RequiresAuthentication
    public WrongStatistics wrongStatisticsForPc(@RequestBody Student student) {
        return wrongStatistics(student.getId());
    }

}
